import sys, time, Image, urllib, socket
#from socket import *
import wx, threading#, cStringIO
import traceback
#import win32com.client
from wx.lib.activexwrapper import MakeActiveXClass
#from win32com.client import Dispatch
from win32com.client.gencache import EnsureModule
from threading import Event, Thread
#from os import getcwd
import os
import pygame
#from wx import *

TIMEOUT=2
serverHost = ""
serverPort = 2001
ImagePort = 8080
url="http://" + serverHost+ ":" + str(ImagePort)
## --------- MainPannel --------------


class MainPanel(wx.Panel):
    def __init__(self, parent, id):


	
        wx.Panel.__init__(self, parent, id, style=wx.BORDER_SUNKEN)
        self.rec = wx.StaticText(self, -1, '127;127' , pos= (10, 70)) #Anzeige der aktuellen Mauszeigerposistion
        self.text = wx.StaticText(self, -1, '127;127' , pos= (10, 100)) #Anzeige der Steuersignale an die Raupe
        self.campos = wx.StaticText(self, -1, '127;127', pos=(10,130)) #Anzeige der Kameraposition
        self.idle=wx.StaticText(self, -1, 'Starting' , pos= (10, 160)) #StatusAnzeige
        self.connect_btn=wx.Button(self, -1, "Connect", (155,10))
        self.licht=wx.CheckBox(self, -1, pos=(40, 190)) #ceckbox Licht
        self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
        wx.StaticText(self, -1, 'Server:', pos=(10, 10))
        wx.StaticText(self, -1, 'Ping:' , pos= (10, 40))
        wx.StaticText(self, -1, "Licht:", pos=(10, 190))
        self.videopanel=wx.Panel(self, -1, pos=(360,10), style=wx.BORDER_SUNKEN, size=(640,480))
        self.videoon=False
        self.ping=wx.StaticText(self, -1, 'no Connection' , pos= (40, 40))
        self.serverid=wx.TextCtrl(self, -1, 'roboterraupe', pos=(50,10))
        self.connected=False
        self.Bind(wx.EVT_BUTTON, self.connect, id=self.connect_btn.GetId())        
        self.licht.Bind(wx.EVT_CHECKBOX, self.OnLichtSchalter)

        self.Refresh_btn=wx.Button(self,-1, "Refresh", pos=(260, 70))
        self.Refresh_btn.Bind(wx.EVT_BUTTON, self.OnChangeResolution)
        
              
        self.res160 = wx.RadioButton ( self, -1, '160x120@25fps',pos=(260, 120), style = wx.RB_GROUP )
        self.res160.Bind(wx.EVT_RADIOBUTTON, self.OnChangeResolution)

        self.res160_5 = wx.RadioButton ( self, -1, '160x120@5fps',pos=(260, 100))
        self.res160_5.Bind(wx.EVT_RADIOBUTTON, self.OnChangeResolution)        

        self.res320 = wx.RadioButton ( self, -1, '320x240@10fps', pos=(260, 140))
        self.res320.Bind(wx.EVT_RADIOBUTTON, self.OnChangeResolution)

        self.res640 = wx.RadioButton ( self, -1, '640x480@5fps', pos=(260, 160))
        self.res640.Bind(wx.EVT_RADIOBUTTON, self.OnChangeResolution)
        
        imageFile = 'Steuer.png'
        raupensteuerung=wx.Image(imageFile, wx.BITMAP_TYPE_PNG).Rescale(250,250)
        self.raupensteuer=wx.BitmapFromImage(raupensteuerung)
        kamerasteuerung=wx.Image(imageFile, wx.BITMAP_TYPE_PNG).Rescale(125,125)
        self.kamerasteuer=wx.BitmapFromImage(kamerasteuerung)      
        self.steuerbutton=wx.BitmapButton(self, -1, bitmap=self.raupensteuer, pos=(50, 230))
        self.rebootbtn=wx.Button(self, -1, "Reboot Server", (250,10))
        self.rebootbtn.Bind(wx.EVT_BUTTON, self.OnServerReboot)
        self.steuerbutton.Bind(wx.EVT_MOTION, self.OnMove)
        self.steuerbutton.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.steuerbutton.Bind(wx.EVT_LEFT_UP, self.OnLeftUp)
        self.steuerbutton.Bind(wx.EVT_LEAVE_WINDOW, self.OnWindowLeave)  
        self.steuerbutton.Bind(wx.EVT_LEFT_DOWN, self.OnLeftDown)
        self.steuerbutton.Bind(wx.EVT_RIGHT_DOWN, self.OnRightDown)
        self.steuerbutton.Bind(wx.EVT_RIGHT_UP, self.OnRightUp)
        self.steuerbutton.Bind(wx.EVT_LEFT_DCLICK, self.OnRightDown)
        self.steuerbutton.Enable(False)
        self.kamerabutton=wx.BitmapButton(self, -1, bitmap=self.kamerasteuer, pos=(115, 60))
        self.kamerabutton.Bind(wx.EVT_LEFT_DOWN, self.OnCamLeftDown)
        self.kamerabutton.Bind(wx.EVT_MOTION, self.OnCamMotion)
        try:
            self.Bind(wx.EVT_CHAR, self.OnLeft)

            self.powerlabel=wx.StaticText(self, -1, '50%', pos=(10, 225))
            self.maxpower=wx.Slider(self, -1, value=50, minValue=0, maxValue=100, pos=(10,240), size=(30,240), style=wx.SL_VERTICAL)
            self.maxpower.Bind(wx.EVT_SLIDER, self.OnPowerSlider)

            self.trimmerlabel=wx.StaticText(self, -1, '0', pos=(30, 505))
            self.Steuertrimmer=wx.Slider(self, -1, value=0, minValue=-50, maxValue=50, pos=(50,500), size=(254,40), style=wx.SL_HORIZONTAL)
            self.Steuertrimmer.Bind(wx.EVT_SLIDER, self.OnTrimmerSlider)
        except:
            traceback.print_exc()
            
    def OnLeft(self, event):
        try:
            print "bla"
            self.sendto("254;127")
        except:
            traceback.print_exc()

    def OnTrimmerSlider(self, event):
        self.trimmerlabel.SetLabel(str(self.Steuertrimmer.GetValue()))

    def OnPowerSlider(self, event):
        self.powerlabel.SetLabel(str(100-self.maxpower.GetValue()) + "%")

    def OnRefresh(self, event):
        
        serverHost = self.serverid.GetValue()
        serverPort = 2001
        ImagePort = 8080
        url="http://" + serverHost+ ":" + str(ImagePort)
        if self.videopanel:
            self.videopanel.Destroy()
        try:
            if self.res640.GetValue():
                self.sendmsg("RES;640")
            if self.res320.GetValue():
                self.sendmsg("RES;320")
            if self.res160.GetValue():
                self.sendmsg("RES;160")
        except:
            self.OnDisconnect()

      
        #self.s.settimeout(None)
        #time.sleep(2)
        #self.vid=self.startvideo(self.videopanel, url)
        self.videopanel=Video(self, -1, url)
    class startvideo(threading.Thread):
        def __init__(self, videopanel, url):
            self.url=url
            self.videopanel=videopanel
        def run(self):
            time.sleep(5)
            self.videopanel=Video(self, -1, url)
            
    def OnChangeResolution(self, event):
        
        serverHost = self.serverid.GetValue()
        serverPort = 2001
        ImagePort = 8080
        url="http://" + serverHost+ ":" + str(ImagePort)
        if self.videopanel:
            self.videopanel.Destroy()
        try:
            if self.res640.GetValue():
                self.sendmsg("RES;640")
            if self.res320.GetValue():
                self.sendmsg("RES;320")
            if self.res160.GetValue():
                self.sendmsg("RES;160")
            if self.res160_5.GetValue():
                self.sendmsg("RES;160_5")                
        except:
            self.OnDisconnect()

      
        #self.s.settimeout(None)
        #time.sleep(2)
        #self.vid=self.startvideo(self.videopanel, url)
        self.videopanel=Video(self, -1, url)
    
    def OnDisconnect(self):
        pass
    
    def OnServerReboot(self, event):
        self.sendmsg("SERVER;REBOOT")
    
    def sendmsg(self, Message):
        self.s.send(Message)
        
    def OnLichtSchalter(self, event):
        if self.licht.GetValue():
            self.sendtocam("127;127;" + self.campos.GetLabel()+";1")
        else:
            self.sendtocam("127;127;" + self.campos.GetLabel()+";254")            

    class keeping (threading.Thread):
        def __init__(self, s, ping, info, connected, connect_btn, steuerbutton, idle):
            self.s=s
            self.ping=ping
            self.info=info
            self.connected=connected
            self.connect_btn=connect_btn
            self.steuerbutton=steuerbutton
            self.idle=idle
            threading.Thread.__init__(self)
            self.stopped=True
            threading.Thread.__init__(self)
        def run(self):
            sleeptime =0.1

            while 1:
                data = False
                time.sleep(sleeptime)
                try:
                    if self.idle.GetLabel()=="Idle":
                        sleeptime=0.5
                    else:
                        sleeptime=0.1
                except:
                    os._exit(99) #exit()
                buf=str(self.info.GetLabel())
                trans=buf.split(";")
                i=0
                tosend=""
                for buf in trans:    
                    tosend+=chr(254)
                    tosend+=chr(i)
                    tosend+=chr(int(buf))
                    i+=1
            
                pingstart=time.clock()
                try:    
                    #pass
                    self.s.send(tosend)
                except:
                    #Fehlerbehandlung!
                    #print "senden beim Pingtransmitter fehlgeschlagen!"
                    self.connected=False
                    self.connect_btn.SetLabel("Connect")
                    self.connect_btn.Enable(True)
                    self.steuerbutton.Enable(False)
                    break
                    #os._exit(99)
                try:
                    self.s.settimeout(TIMEOUT)
                    #if not self.stopped:
                    data=self.s.recv(1024)
                except:
                    self.ping.SetLabel("Timeout" )
                    self.connected=False
                    self.connect_btn.SetLabel("Connect")
                    self.connect_btn.Enable(True)
                    self.steuerbutton.Enable(False)
                    break
                    #os._exit(99)
                    
                pingende=time.clock()
                #if True: #s.getpeername()[0]!='127.0.0.1':
                #    while int((pingende-pingstart)*1000) == 0:
                #        try:
                #            data=self.s.recv(1024)
                #        except:
                #            self.connected=False
                #            self.connect_btn.SetLabel("Connect")
                #            self.connect_btn.Enable(True)
                #            self.steuerbutton.Enable(False)
                #            exit()
                #        pingende=time.clock()
                if data:
                    #print data
                    aktping=(pingende-pingstart)*1000
                    try:
                        self.ping.SetLabel(str(int(aktping)) + "ms" )
                    except:
                        os._exit(99)

        
    def connect(self,event):
        
        serverHost = self.serverid.GetValue()
        serverPort = 2001
        ImagePort = 8080
        url="http://" + serverHost+ ":" + str(ImagePort)

        if not self.videoon:
            #self.videopanel.Destroy()
            self.videopanel=Video(self, -1, url)
            self.video=True
          
        try:
            self.s.close()
        except:
            pass
        
        try:
            self.s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.s.settimeout(TIMEOUT)
            self.s.connect((serverHost, serverPort)) # connect to server on the po
            self.connect_btn.SetLabel("Connected")
            self.connect_btn.Enable(False)
            self.steuerbutton.Enable(True)
            self.k=self.keeping(self.s, self.ping, self.text, self.connected, self.connect_btn, self.steuerbutton, self.idle)
            self.k.start()
        except:
            self.connect_btn.Enable(True)
            self.steuerbutton.Enable(False)           


    def sendtocam(self, temp):
#        self.k.stopped=True
        if temp != self.campos.GetLabel():
            trans=temp.split(";")
            i=2
            tosend=""
            for buf in trans:
                tosend+=chr(254)
                tosend+=chr(i)
                tosend+=chr(int(buf))
                i+=1
            self.text.SetLabel(temp)    
#        self.k.stopped=False

    def sendto(self, temp):
        #self.pinger.cancel()
        i=0
        #self.k.stopped=True
        if temp == self.text.GetLabel():
            self.k.stopped=False
            return
        else:
            self.k.stopped=True
            
        trans=temp.split(";")
        i=0
        tosend=""
        for buf in trans:
            tosend+=chr(254)
            tosend+=chr(i)
            tosend+=chr(int(buf))
            i+=1
        self.text.SetLabel(temp)
#       self.k.stopped=False
        
    def calcpos(self, pt):
        
        xo=(pt[0]-127)
        yo=(pt[1]-127)*-1
        x=yo
        y=yo
        if yo >= 0:
            if xo >= 0:
                y+=-xo
                if y > 0: x=xo+y
                else: x=xo
            else:
                x+=xo
                if x > 0: y=yo
                else: y=yo-x
        else:
            if xo >= 0:
                x+=xo
                if x > 0:
                    x=xo+yo
                    y=-xo
            else:
                y=-xo+yo
                if y > 0: x=xo
           
        x=int((x*((110-self.maxpower.GetValue())/100.0)))+127

        y=int((y*((110-self.maxpower.GetValue())/100.0)))+127


        if x>127:        
            x=x+self.Steuertrimmer.GetValue()
        else:
            x=x-self.Steuertrimmer.GetValue()
            
        if y>127:
            y=y-self.Steuertrimmer.GetValue()
        else:
            y=y+self.Steuertrimmer.GetValue()
        if x < 0  : x = 0
        if y < 0  : y = 0
        if x > 254: x = 254
        if y > 254: y = 254
        #print (str(x) + ";" + str(y)) 
        return (str(x) + ";" + str(y))       
        
    def calccampos(self, pt, faktor=1):
        y=(pt[0])*faktor
        x=(pt[1])*faktor
        
        if x < 0  : x = 0
        if y < 0  : y = 0
        if x > 254: x = 254
        if y > 254: y = 254
        
        
        return(str(x) + ";" + str(y))

    def stopp(self):
        self.k.stopped=True
        self.idle.SetLabel("Idle")
        self.sendto("127;127")
       

    def OnWindowLeave(self, event):
        self.stopp()
        
    def OnLeftUp(self, event):
        self.k.stopped=True
        self.leftmousedown=False
        self.stopp()

    def OnRightUp(self, event):
        self.k.stopped=True
        self.leftmousedown=False
        self.stopp()
        
    def OnMove(self, event):
        
        pt = event.GetPosition()
        self.leftmousedown=False
        if event.LeftIsDown():
            self.k.stopped=True
            #time.sleep(0.1)
            self.idle.SetLabel("Driving")
            self.sendto(self.calcpos(pt))
            
        if event.RightIsDown():
            self.k.stopped=True
            #time.sleep(0.1)
            self.sendtocam("127;127;" + self.calccampos(pt, 1))
            self.idle.SetLabel("Moving Cam")
            self.campos.SetLabel(self.calccampos(pt, 1))
        self.rec.SetLabel(self.calcpos(pt))

    def OnLeftDown(self, event):
        self.k.stopped=False
        self.leftmousedown=True
        #time.sleep(0.1)
        self.idle.SetLabel("Keep")
        pt = event.GetPosition()
        self.sendto(self.calcpos(pt))
    
    def OnRightDown(self, event):
        #time.sleep(0.1)
        self.idle.SetLabel("Moving Cam")
        pt = event.GetPosition()
        self.sendtocam("127;127;" + self.calccampos(pt, 1))
        self.campos.SetLabel(self.calccampos(pt, 1))

    def OnCamLeftDown(self, event):
        self.idle.SetLabel("Moving Cam")
        pt = event.GetPosition()
        self.sendtocam("127;127;" + self.calccampos(pt, 2))
        self.campos.SetLabel(self.calccampos(pt, 2))

    def OnCamMotion(self, event):
        pt = event.GetPosition()
        if event.LeftIsDown():
            self.k.stopped=True
            self.sendtocam("127;127;" + self.calccampos(pt, 2))
            self.idle.SetLabel("Moving Cam")
            self.campos.SetLabel(self.calccampos(pt, 2))
        #self.rec.SetLabel(self.calcpos(pt))

        
class Video(wx.Panel):
    def __init__(self, parent, id, url):
        wx.Panel.__init__(self, parent, id, pos=(360,10), style=wx.BORDER_SUNKEN, size=(640,480))
        
        browserModule=EnsureModule("{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 1, 0)
        #browserModule=EnsureModule("{EAB22AC0-30C1-11CF-A7EB-0000C05BAE0B}", 0, 1, 1)
        theClass=MakeActiveXClass(browserModule.WebBrowser)
        self.ie=theClass(self, 10)
        self.ie.SetPosition((-25,-20))
        self.ie.SetSize((700,500))
        self.SetAutoLayout(True)

        self.whenDocComplete=True
        #time.sleep(5)
        self.ie.Navigate2(url+"/AppletWin2.html")


    def OnDocumentComplete(self, *others):
        #pass
        print "... inside OnDocumentComplete"
        self.whenDocComplete.set()
        print "    event set inside OnDocumentComplete"
        raise Exception, "... inside OnDocumentComplete"
        
        
class Communicate(wx.Frame):
    def __init__(self, parent, id, title):
        wx.Frame.__init__(self, parent, id, title)
        
        panel=wx.Panel(self,-1)
        #self.video=Video(panel, -1)
        self.mainPanel=MainPanel(panel,-1)
        #self.rightPanel=RightPanel(panel,-1, s) 
        #s=self.leftPanel.s
        
        hbox=wx.BoxSizer()
        hbox.Add(self.mainPanel, 1, wx.EXPAND | wx.ALL, 5)
        #hbox.Add(self.rightPanel, 1, wx.EXPAND | wx.ALL, 5)
        panel.SetSizer(hbox)
        self.Centre()
        #self.ShowFullScreen(True)
        #btn = wx.Button(self.leftPanel, -1, u"Click me...")
        #hbox.Add((0, 0), 1)
        #hbox.Add(btn, 0, wx.ALIGN_CENTER_HORIZONTAL | wx.ALL, 10)
        #hbox.Add((0, 0), 1)
        #btn.Bind(wx.EVT_BUTTON, self.show_message)
        #self.Bind(wx.EVT_CLOSE, self.OnClose)
        self.Show(True)
        self.Maximize()
#        print self.GetSize()
        #buf=str(self.rightPanel.text.GetLabel())
                                                                
    def OnClose(self, event):
        self.mainPanel.videopanel.Destroy()
        self.Destroy()
        #pass
        #os._exit(99)




app = wx.App()
Communicate(None, -1, 'Roboter Steuerung')
app.MainLoop()
os._exit(99)
